package com.itcam.map.hashmap;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.TreeMap;

/**
 * @author : Cammy.Wu
 * Description : 
 */

public class HashMapDemo02 {
    /*
    双列集合底层的数据结构, 都是针对于键有效, 跟值没有关系.

        HashMap : 键唯一 (重写hashCode和equals方法)
        TreeMap : 键排序 (实现Comparable接口, 重写compareTo方法)
        LinkedHashMap : 键唯一, 且可以保证存取顺序


        Todo:HashMap底层原理 :
                    Java8之前：数组+链表 添加在哈希表中使用的是头插法
                    Java8之后：数组+链表+红黑树 添加在数组索引下使用的是尾插法，就是直接插后面，链表长度>8&&数组长度>=64，就会把链表自动转为红黑树
                        当调用map.put(k,v);先把k，v封装为Entry对象，他是专门表示键值对的对象，随后
                            从Entry对象取出键进行操作，计算索引位置，跟值无关。
                        索引位置的计算：先调对象hashCode方法得到原始hash值，再把原始hash值向右移动16位进行扰动hash，
                            再拿着扰动后的hash跟原始hash做异或操作进行二次hash，二次hash后再去模于数组的长度来计算索引位置。
                            注意：源码中不是直接模于数组长度，而是数组长度-1再与上hash值
 */
    public static void main(String[] args) {
        showLinkedHashMap();
    }

    // 键排序
    private static void showTreeMap() {
        TreeMap<Person, String> tm = new TreeMap<>();
        tm.put(new Person("李四", 24), "上海");
        tm.put(new Person("张三", 23), "北京");
        tm.put(new Person("王五", 25), "成都");
        tm.put(new Person("赵六", 25), "成都");
        System.out.println(tm);
    }

    // 键唯一
    private static void showHashMap() {
        HashMap<Person, String> hm = new HashMap<>();
        hm.put(new Person("李四", 24), "上海");
        hm.put(new Person("张三", 23), "北京");
        hm.put(new Person("王五", 25), "成都");
        hm.put(new Person("王五", 25), "成都");
        System.out.println(hm);
    }

    // 键唯一，同时保证存储顺序
    private static void showLinkedHashMap() {
        LinkedHashMap<Person, String> hm = new LinkedHashMap<>();
        hm.put(new Person("李四", 24), "上海");
        hm.put(new Person("张三", 23), "北京");
        hm.put(new Person("王五", 25), "成都");
        hm.put(new Person("王五", 25), "成都");
        System.out.println(hm);
    }
}
